package task;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.swt.graphics.ImageData;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

import task.dao.ObjectDb;
import util.JdbcUtil;


public class CountRows extends DbTask {
	@Override
	protected void doRun(Map<String, String> props) throws SQLException {
		String schema = props.get("schema");
		String countFile = props.get("countFile");
//		checkMissingAndExcessiveTables(schema);
		System.out.printf("Number of tables in schema: '%s'%n", schema);
		if (dbType == DbType.ORACLE) { 
			try {
				System.out.printf("%s%n", JdbcUtil.getSingleString(conn(), String.format("select count(*) from all_tables where owner=upper('%s')", schema)));
			} catch (SQLException e1) {
				throw new RuntimeException(e1);
			}
		}
		System.out.printf("Count rows for schema '%s':%n", schema);
		String[] tables = getTablesInSchema(schema);
		HashMap<String, Object> countMap = new HashMap<String, Object>();
		for (String name : tables) {
			try {
				String sql = String.format("select count(*) from %s.%s", schema, name);
				Statement stmt = conn().createStatement();
				ResultSet rs = stmt.executeQuery(sql);
				rs.next();
				String value = rs.getString(1);
				countMap.put(name, value);
				if (!"0".equals(value)) {
					System.out.printf("%7s : %s%n", value, name);
				}
				rs.close();
				stmt.close();
			} catch (SQLException e) {
				throw new RuntimeException(e);
			}
		}
		processDiff(countFile, countMap);
	}

	private void processDiff(String countFile, HashMap<String, Object> countMap) {
		if (countFile == null || countFile.trim().length()==0) {
			System.out.printf("No countFile specified%n");
			return;
		}
		System.out.printf("%n  === Differences since last run ===%n%n");
		File file = new File(countFile);
		try {
			XStream xs = new XStream(new DomDriver());
			if (file.isFile()) {
				FileReader is = new FileReader(file);
				Map<String, String> prevMap = (Map<String, String>) xs.fromXML(is);
				for (Map.Entry<String, Object> e : countMap.entrySet()) {
					String prevI = prevMap.get(e.getKey());
					String currI = (String) e.getValue();
					int prev = prevI == null ? 0 : Integer.parseInt(prevI);
					int curr = currI == null ? 0 : Integer.parseInt(currI);
					if (curr != prev) {
						System.out.printf("%30s : %4s : %4s (%s)%n",
								e.getKey(), prev, curr, curr - prev);
					}
				}
			}
			FileWriter os = new FileWriter(file);
			xs.toXML(countMap, os);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

//	private void checkMissingAndExcessiveTables(String schema) {
//		try {
//			String sql = String.format("select table_name from all_tables where owner=upper('%s')", schema);
//			HashSet<String> actual = new HashSet<String>();
//			Statement stmt = conn.createStatement();
//			ResultSet rs = stmt.executeQuery(sql);
//			while (rs.next()) {
//				actual.add(rs.getString(1).toLowerCase());
//			}
//			rs.close();
//			stmt.close();
//			ArrayList<String> missing = new ArrayList<String>();
//			for (String table : TABLES) {
//				if (!actual.contains(table)) {
//					missing.add(table);
//				} else {
//					actual.remove(table);
//				}
//			}
//			if (missing.size()>0) {
//				System.out.printf("Missing tables : %s%n", missing);
//			}
//			if (actual.size()>0) {
//				System.out.printf("Excessive tables : %s%n", actual);
//			}
//		} catch (SQLException e) {
//			throw new RuntimeException(e);
//		}
//	}

	@Override
	public String getDescription() {
		String desc = "Count the rows of all NetMaster tables\nIf countFile is set, the count will be compared to last saved run, and saved.";
		return desc;
	}

	@Override
	public ImageData getImageData() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String[] propertyNames() {
		String[] props = { "schema", "countFile" };
		return props;
	}
}
